#include <iostream>
#include <string>
#include <cstring>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <sys/socket.h>
#include <assert.h>
static void Usage(std::string name)
{
    std::cout << "Usage:\n\t" << name << " server_ip server_port" << std::endl;
}

// udpClient server_ip server_port
//  如果一个客户端要连接server必须知道server对应的ip和port
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }
    // 1.根据命令行 设置要访问的服务器IP
    std::string server_ip = argv[1];
    uint16_t server_port = atoi(argv[2]);

    // 2.创建客户端
    //  2.1 创建socket
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    assert(sockfd > 0);

    // 2.2 client 不需要bind
    // 所谓的"不需要" 指的是：不需要用户自己bind端口信息 因为OS会自动给你绑定
    // 如果我们非要自己bind 可以 但是不推荐
    // 所有的客户端软件<- ->服务器 通信的时候 必须得有client[ip:port] <-->serve[ip:port]
    // 为什么？client很多，不能给客户bind指定的port，因为port可能被别的client使用了
    // 你的client就无法启动了
    // 2.2 填写服务器信息
    struct sockaddr_in server;
    bzero(&server, sizeof server);
    server.sin_family = AF_INET;
    server.sin_port = htons(server_port);
    server.sin_addr.s_addr = inet_addr(server_ip.c_str());

    // 3.通信过程
    std::string buffer;
    while (true)
    {
        std::cout << "Please Enter# ";

        std::getline(std::cin, buffer);
        // 发送消息给sever
        // 首次调用sendto函数的时候 我们的client
        sendto(sockfd, buffer.c_str(), buffer.size(), 0,
               (const struct sockaddr *)&server, sizeof(server));

        //接受
        //这一块还是存在bug?
        char buffer[1024];
        struct sockaddr_in temp;
        socklen_t len = sizeof(temp);
        ssize_t s =recvfrom(sockfd,buffer,sizeof(buffer),0,(struct sockaddr*)& temp,&len);
        if(s>0)
        {
            buffer[s] = 0;
            std::cout<<"server echo#"<<buffer<<std::endl;
        }
        
    }

    return 0;
}